/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package nsip.scheduling;

import java.util.Iterator;
import java.util.List;
import nsip.model.Item;
import org.uncommons.watchmaker.framework.FitnessEvaluator;

/**
 *
 * @author Markus Goetz
 */
public class ScheduleEvaluator implements FitnessEvaluator<AbstractSchedule> {

    @Override
    public double getFitness(AbstractSchedule candidate, List<? extends AbstractSchedule> others) {
        double averageUtilization = candidate.getAverageUtilization();
        double standardDeviation = 0.0;
        Iterator<Day> daysIterator = candidate.getDaysIterator(candidate.getCurrentDate());

        int totalStoragePenalty = 0;
        int itemCount = 0;
        
        while (daysIterator.hasNext()) {
            Day day = daysIterator.next();
            for (Item item: day.getItems()) {
                int storageTime = item.getProductionDueDate() - day.getDate();
                if (storageTime >= 0) {
                    totalStoragePenalty += storageTime * item.getQuantity();
                    itemCount += item.getQuantity();
                }
            }
            
            standardDeviation += Math.pow(averageUtilization - day.getUtilization(), 2);
        }
        standardDeviation = Math.sqrt(standardDeviation);

        double averageStoragePenalty = (
                itemCount > 0 ? totalStoragePenalty / itemCount :
                    (AbstractSchedule.POSSIBLE_ORDER_PRODUCTION_DAYS - 1 / 2));
        
        double score = 100 * averageUtilization +
            30 / (1 + Math.sqrt(standardDeviation)) +
            100 / Math.sqrt(averageStoragePenalty + 1);
        
        return score;
    }

    @Override
    public boolean isNatural() {
        return true;
    }
}
